import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
import javax.swing.*;
import javax.xml.soap.Text;

class f_frame extends JFrame implements ActionListener{
    //由于text内容需要改变，下面会用到，因此需要拎出来
    //新建名为text的JTextField文本框位置，用于点击是数字的实时变化显示以及最终的结果显示
    JTextField text=new JTextField("");
    public f_frame()
    {
        //创建界面,设置其大小为固定值，宽900，高650，使整个界面都可以正常显示
        JFrame f=new JFrame("计算器");
        f.setSize(900, 650);
        Container con=f.getContentPane();
        //创建1个底色为白色的JPanel，设置其格式为固定格式（即可以自定义的格式）
        JPanel p=new JPanel();
        p.setBackground(Color.white);
        p.setLayout(null);
        //并将text可编辑性设置为用户不可编辑，设置其长宽以及背景颜色。
        text.setEditable(false);
        text.setBackground(new Color(221, 221, 221));  //背景色--灰色
        text.setBounds(100, 50, 700, 50);
        text.setFont(new Font("宋体", Font.BOLD, 25));
        text.setHorizontalAlignment(JTextField.RIGHT); //右对齐
        p.add(text);                                   //添加到JPanel中
        //创建JButton数组，包含界面从左到右、自上而下的所有按钮
        JButton[] buttongroup= {
                new JButton("7"), new JButton("8"), new JButton("9"),
                new JButton("/"),new JButton("CE"),
                new JButton("4"), new JButton("5"), new JButton("6"),
                new JButton("*"),new JButton("="),
                new JButton("1"), new JButton("2"), new JButton("3"),
                new JButton("-"),
                new JButton("0"), new JButton("."),
                new JButton("+")
        };
        //遍历JButton数组，设置每个按钮的颜色、字体字号以及具体位置
        for(int i=0; i<buttongroup.length; i++){
            JButton b1=buttongroup[i];
            b1.setBackground(new Color(204, 204, 255));
            b1.setFont(new Font("宋体", Font.BOLD, 25));
            b1.addActionListener(this);
            //位置逻辑，“=”和“0”特判，占据空间略大，其余长宽一致，规律放置
            if(i<9){
                if(i<5) b1.setBounds(100+150*i, 150, 100, 50);
                else b1.setBounds(100+150*(i-5), 250, 100, 50);
            }
            else if(i==9)
                b1.setBounds(100+150*(i-5), 250, 100, 250);
            else if(i==14)
                b1.setBounds(100, 450, 250, 50);
            else {
                if(i<14) b1.setBounds(100+150*(i-10), 350, 100, 50);
                else b1.setBounds(100+150*(i-13), 450, 100, 50);
            }
            p.add(b1);
        }
        //向界面中添加JPanel变量，并设置界面可见性为true
        con.add(p);
        f.setVisible(true);
        //最后设置界面可见性，否则将会出现加载不到界面内容，
        //必须有鼠标事件才能成功加载的现象发生。
    }
    //由于优先级的不同，算式中最多需要保留3个操作数，
    //分别按顺序记作num1, num2, num3，初始值为0
    //point变量存储当前按键
    double num1=0.0, num2=0.0, num3=0.0, point=1.0;
    //操作符用int型数据表1:+, 2:-, 3:*, 4:\
    //op存储上一操作符， op_now存储当前读入操作符，
    //op_greater存储优先级较高的后面的操作符
    int op=0, op_now=0, op_greater=0;
    //标志设计
    Boolean flag_num=false;      //true：num1输入完毕 false：num2尚未输入完毕
    Boolean flag_point=false;    //true：当前数字有小数点 false：当前数字无小数点
    Boolean flag_mistake=false;  //true：输入存在错误 false：输入尚不存在错误
    Boolean flag_begin=false;
    //true：从上一次输入符号（非等号）起，已经按下某（或某些）数字
    Boolean flag_greater=false;  //true：有较高的优先级计算须先处理
    Boolean flag_end=false;      //true：上一个按下的按键是"="，结束了一次计算
    //响应按钮事件的函数
    //采用按键实时计算的方式，考虑算符优先级的影响
    public void actionPerformed(ActionEvent e)
    {
        //捕获事件来源
        JButton btn=(JButton) e.getSource();
        //上一次按键出错，再次按键需更新错误信息。设置文本为空
        if(flag_mistake)
        {
            flag_mistake=false;
            text.setText("");
        }
        //获取事件来源按键的内容，方便后续操作
        String s=btn.getText();
        switch(btn.getText())
        {
            case "CE":
                //按下清空键，设置各标志以及各项纪录数据为初始状态，设置文本框内容为空
                flag_point=flag_num=flag_mistake=flag_begin=flag_greater=flag_end=false;
                num1=num2=num3=0.0; point=1.0; op=0;
                text.setText("");
                break;
            case "0": case "1": case "2": case "3": case "4":
            case "5": case "6": case "7": case "8": case "9":
            //按下数字键，首先已有数字键入，更新flag_begin标志
            flag_begin=true;
            //假设上一按下按键为"="，再次按下数字后，更新文本按下数字，恢复flag_end标志为0
            //假设不成立，则在文本框内容后附加该数字即可
            if(flag_end==true)
            {
                text.setText(btn.getText());
                flag_end=false;
            }
            else text.setText(text.getText()+btn.getText());
            //该数字已经输入小数点后，需要更新小数位数
            if(flag_point)
                point=0.1*point;
            //根据flag_greater、flag_num的信息更新存储的数字
            if(flag_greater) num3=num3*10+s.charAt(0)-'0';
            else if(!flag_num) num1=num1*10+s.charAt(0)-'0';
            else num2=num2*10+s.charAt(0)-'0';
//			System.out.print(num1+" "+num2+" "+num3+"\n");
            break;
            case ".":
                //在小数点前没有按下任何数字,则在前面补0
                if(flag_begin==false) text.setText("0");
                //跟新flag_point并向文本框中添加小数点
                if(!flag_point)  //条件是为了避免同一数字输入过多小数点
                {
                    flag_point=true;
                    text.setText(text.getText()+".");
                }
                break;
            default:
                //输入符号时，检查操作数是否足够，不够则报错并相应进行标志及存储数据的设置
                //然后对个存储数据进行小数化的处理，若有高优先级的运算须先进行，也在这里处理
                if(flag_begin==false)
                {
                    text.setText("mistack!need more number!");
                    flag_mistake=true;
                    flag_point=flag_num=flag_greater=flag_end=false;
                    num1=num2=num3=0.0; point=1.0; op=0;
                }
                else
                {
                    if(flag_greater) num3=point*num3;
                    else if(!flag_num) num1=point*num1;
                    else num2=point*num2;
                    //恢复小数位数标定  设置数据num1以获取以及小数重新开始计的相关标志
                    point=1.0;
                    flag_num=true; flag_point=false;
                    //计算需要先进行的高优先级计算段
                    if(flag_greater)
                    {
                        num2=mul(num2, num3, op_greater);
                        num3=0.0;
                        flag_greater=false;
                    }
                }
        }
        if(flag_begin)
        {
            flag_begin=false;
            //若按键为"+" "-" "*"或"\"则记录当前操作符
            //若按键为"="，则完成最后一次计算并显示结果
            switch(btn.getText())
            {
                case "+":
                    text.setText(text.getText()+"+");
                    op_now=1; break;
                case "-":
                    text.setText(text.getText()+"-");
                    op_now=2; break;
                case "*":
                    text.setText(text.getText()+"*");
                    op_now=3;
                    break;
                case "/":
                    text.setText(text.getText()+"/");
                    op_now=4;
                    break;
                case "=":
//				System.out.println(num1+" "+num2+" ");
                    if(op!=0)
                    {
                        num1=mul(num1, num2, op);
                        num2=0.0;
                    }
                    if(!flag_mistake)
                        text.setText(String.valueOf(new DecimalFormat("0.0000").format(num1)));
                    op=0; point=1.0;
                    flag_end=true;
                    break;
                default: flag_begin=true;
                    //最终效果：+-*\=号，则flag_begin为false，否则为true
            }
            //进行优先级比较以及计算简化的操作
            if(!flag_begin&&btn.getText()!="=")
            {
                if(op==0) op=op_now; //第一个算符不需要任何多余操作，存下来就行了
                else if(op_now>=3&&op<3)
                {
                    //若当前算符优先级大于前一算符，
                    op_greater=op_now;
                    flag_greater=true;
                }
                else
                {
                    //否则，完成前一算符的计算，将结果更新到num1，设置num2为0，更新算符
                    num1=mul(num1, num2, op);
                    num2=0.0;
                    op=op_now;
                    flag_greater=false;
                }
            }
        }
    }
    //真正进行计算的模块
    //传参：a为第一操作数，b为第二操作数，operator为算符（1:+, 2:-, 3:*, 4:\）
    public double mul(double a, double b, int operator)
    {
//		System.out.print(a+" "+b+"\n"); 
        double ans=0.0;    //ans用于存储要返回的计算结果
        switch(operator)
        {
            case 1: ans=a+b; break;
            case 2: ans=a-b; break;
            case 3: ans=a*b; break;
            case 4:
                //除法党除数为0时进行报错，设置相应的标志以及状态为恢复初始状态
                if(b!=0) ans=a/b;
                else
                {
                    System.out.println("mistake accoure");
                    text.setText("mistack!devise 0!");
                    flag_mistake=true;
                    flag_point=flag_num=flag_begin=flag_greater=flag_end=false;
                    num1=num2=num3=0.0; point=1.0; op=0;
                }
        }
        return ans;
    }
    //主函数，创建界面
    public static void main(String args[])
    {
        f_frame page=new f_frame();
    }
}